AWS Step FunctionsとAWS Lambdaを使用してサーバーレスワークフローを作成してみた
このブログでは、AWS Step Functionsを使用して、複数のAWS Lambda関数を統合するサーバーレスワークフローを設計し、実行する方法について紹介します。
はじめに
AWS Step Functions は、デベロッパーが分散アプリケーションの構築、IT およびビジネスプロセスの自動化、AWS のサービスを利用したデータと機械学習のパイプラインの構築に使用するローコードのビジュアルワークフローサービスです。ワークフローは、障害、再試行、並列化、サービス統合、可観測性などを管理するため、デベロッパーはより価値の高いビジネスロジックに集中することができます。
最近、次の記事でAWS Step Functionsについて学びました。
- https://aws.amazon.com/jp/step-functions/?nc1=h_ls&step-functions.sort-by=item.additionalFields.postDateTime&step-functions.sort-order=desc
- https://aws.amazon.com/jp/getting-started/hands-on/create-a-serverless-workflow-step-functions-lambda/?nc1=h_ls
- https://lumigo.io/aws-serverless-ecosystem/aws-step-functions-limits-use-cases-best-practices/
Step Functionsとは
AWS Step Functionsは、サーバーレスオーケストレーションです。ロジックを使用して、アプリケーションのワークフローを個別に設計し、管理できます。
- Step Functionsを使用すると、アプリケーション開発がより速く、より直感的になります。
- 複数のLambda関数を、簡単にデバッグと変更ができる柔軟なワークフローに容易に統合できます。 ステップ関数は、追加のロジックを必要とせずに、アプリケーションの各ステップを簡単にトリガーおよび追跡できます。
- Step Functionsコンソールは、アプリケーションロジックの視覚化に役立つ、ステートマシンのグラフィック表現を提供します。
-
Step Functionsを使用して作成するワークフローはステートマシン(State Machine)と呼ばれ、ワークフローの各ステップはステート(States)と呼ばれます。
Step Functionsのしくみ
- Workflow Studioでビジュアルワークフローを定義します。コンソールがコードを自動生成します。コンソールでコードスニペットを使用して自分でコーディングすることも、VSCodeを使用してローカルでコーディングすることもできます。
- ワークフローでトリガーするリソースを指定します。
- 実行を開始して、ワークフローのステップが意図したとおりに動作していることを確認します。コンソールから直接実行履歴を検査し、デバッグします。
Lambda関数を使用したStep Functions
飲み物を注文するアプリケーションのワークフローを例に挙げたいと思います。AWS Lambdaコンソールを開き、[関数の作成]をクリックします。下図の設定内容を設定し、Lambda関数を作成します。同様に他のLambda関数(Coffee_Function、Juice_Function)も作成します。ワークフローの名前は「DrinksOrderApplication」です。まず、ワークフローを視覚化します。3つのLambda関数と、Choice stateとFallback stateで構成します。
- Order – 注文の詳細を入力値として送信するタスクです。
- Drinks – 次のステップ(コーヒーまたはジュース)を選択するための入力値として注文の詳細を使用するのは、Choice Stateです。
- Coffee – Lambda関数によって実装されるタスクです。
- Juice – Lambda関数によって実装されるタスクです。
- Fallback - States.Runtimeエラーをキャッチします。
ステップ 1 : ステートマシンとサーバーレスワークフローを作成する
AWS Step Functionsコンソールを開きます。[ステートマシンを作成する]をクリックし、「コードでワークフローを記述」を選択します。 「次へ」をクリックします。
「ステートマシン名」に「OrderStateMachine」と入力します。
[既存のロールを選択する]を選択し、Lamdaを実行できる役割をドロップダウンから選択します。
新しいIAMロールを作成することもできます。この手順に従って、新しいIAMロールを作成します。
- Identity and Access Management(IAM)コンソールに移動します。
- [ロールを作成]をクリックし、信頼されたエンティティタイプからAWSサービスを選択し、ユースケースからLambdaを指定し、[次へ]をクリックします。
- [ポリシーの作成]をクリックします。
- 下図のように詳細を設定します。
- [次のステップ:タグ]を選択します。
- [次のステップ:確認]を選択し、ポリシー名を入力し、[ポリシーの作成]をクリックします。
ステップ 2 : Lambda関数を作成する
ステートマシンを作成したので、ワークフローを設計できます。このタスクでは、ステートマシン用に3つのLambda関数を作成する必要があります。AWS Lambdaコンソールを開き、[関数の作成]をクリックします。 下図の設定内容を設定し、Lambda関数を作成します。
同様に他のLambda関数(Coffee_Function、Juice_Function)も作成します。
OrderLambdaFunction
これは、注文の詳細を入力として受け取り、注文情報を処理するLambda関数です。
import json def lambda_handler(event, context): Order = { "OrderType" : "Drinks", "DrinksCategory" : event['DrinksCategory'], "DrinksType" : event['DrinksType'] } return Order
Coffee_Function
Drink_StateはChoice_Stateです。 Drink Category がコーヒーの場合、Coffee_FunctionのLambda関数が呼び出されます。 コーヒーの注文内容に応じて、金額の情報を返します。
import json def lambda_handler(event, context): OrderType = event['OrderType'] DrinksCategory = event['DrinksCategory'] DrinksType = event['DrinksType'] Price = getPrice(OrderType, DrinksCategory, DrinksType) print("Price : ", Price) return { 'OrderType' : OrderType, 'DrinksCategory': DrinksCategory, 'DrinkType': DrinksType, 'Price': Price } def getPrice(OrderType, DrinksCategory, DrinksType): print(OrderType, " ", DrinksCategory, " " , DrinksType) if (OrderType == "Drinks" and DrinksCategory == "Coffee" and str(DrinksType) == "Cappuccino"): return "¥300" elif (OrderType == "Drinks" and DrinksCategory == "Coffee" and str(DrinksType) == "Espresso"): return "¥500" else: return "This drink is not available!"
Juice_Function
Drink Category がジュースの場合、Juice_FunctionのLambda関数が呼び出されます。ジュースの注文内容に応じて、金額の情報を返します。
import json def lambda_handler(event, context): OrderType = event['OrderType'] DrinksCategory = event['DrinksCategory'] DrinksType = event['DrinksType'] Price = getPrice(OrderType, DrinksCategory, DrinksType) print("Price : ", Price) return { 'OrderType' : OrderType, 'DrinksCategory': DrinksCategory, 'DrinksType': DrinksType, 'Price': Price } def getPrice(OrderType, DrinksCategory, DrinksType): print(OrderType, " ", DrinksCategory, " " , DrinksType) if (OrderType == "Drinks" and DrinksCategory == "Juice" and str(DrinksType) == "Orange"): return "¥300" elif (OrderType == "Drinks" and DrinksCategory == "Juice" and str(DrinksType) == "Strawberry"): return "¥500" else: return "This drink is not available!"
ステップ 3 : ステートマシン定義の書き込み
AWS Step Functionsコンソールを開きます。編集をクリックします。ステートマシン定義ウィンドウの内容を「OderStateMachine」定義に置き換えます。
ワークフローの定義
{ "Comment": "Order Process State Machine", "StartAt": "Order", "States": { "Order": { "Type": "Task", "Resource": "arn:aws:lambda:XXXX:function:orderfunction", "Next": "Drinks" }, "Drinks": { "Type": "Choice", "Choices": [ { "Variable": "$.DrinksCategory", "StringEquals": "Coffee", "Next": "Coffee" }, { "Variable": "$.DrinksCategory", "StringEquals": "Juice", "Next": "Juice" } ] }, "Coffee": { "Type": "Task", "Resource": "arn:aws:lambda:XXXX:function:coffee_function", "Catch": [ { "ErrorEquals": [ "States.TaskFailed" ], "Next": "fallback" } ], "End": true }, "Juice": { "Type": "Task", "Resource": "arn:aws:lambda:XXXX:function:juice_function", "Catch": [ { "ErrorEquals": [ "States.TaskFailed" ], "Next": "fallback" } ], "End": true }, "fallback": { "Type": "Pass", "Result": "Hello, AWS Step Functions!", "End": true } } }
ワークフローの視覚化
ステップ 4 : ステートマシンをテストする
ワークフローのステップが期待通りに動作することを確認します。「新しい実行」を選択し、「入力」にJSONで入力値を指定し、「実行の開始」をクリックします。
コンソールのグラフインスペクターに、現在のステータスが表示されます。ワークフロー図で各ステップをクリックすると、ステップに関する情報(詳細・ステップ入力・ステップ出力)を確認できます。
実行イベント履歴から、実行履歴のログと各ステップのステータスを確認できます。CloudWatchログを確認することもできます。
まとめ
このブログでは、インプットに応じて異なるLambda関数を呼び出すOrderStepFunctionワークフローを作成し、AWS Step Functionsの基本についてご紹介しました。AWS Step Functionsを使用すると、ワークフローをステートマシンとして定義し、複雑なコードをわかりやすいステートメントとダイアグラムに変換できます。これにより、マルチステップシステムの構築が簡単になります。
このブログがお役に立てば幸いです。Step Functionsを使用してみてください。